package com.ixonos.cloud;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.text.format.Time;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.ViewFlipper;

import java.io.InputStreamReader;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class Cloud extends AppWidgetProvider {
	static final String TO_GRAPHIC_VIEW = "to_graphic_view";
	static final String TO_NUMERIC_VIEW = "to_numeric_view";
	static final String REFRESH_NUMERIC = "refresh_numeric";
	static final String REFRESH_GRAPHIC = "refresh_graphic";
	static final String WEAATHER_URL = "http://www.google.com/ig/api?hl=zh_cn&weather=";
	static final String TAG = "Weather";
	static final int TIMER_COMPLETED = 1;
	static final int WEATHER_COMPLETED = 2;

	static RemoteViews rv;
	static AppWidgetManager widgetMgr;
	static ComponentName componentName;
	
	static String actualTemperature;
	static String highTemperature;
	static String lowTemperature;
	
	static boolean isNumericView = true;// otherwise is graphic view
	Timer timer = new Timer();  

	static final int TURN = 11 * 5;
    static Thread mThread = null;
    boolean loadWeather = false; 

    // 111
	static final int thermometerImageArray[] = { R.drawable.thermometer_0, R.drawable.thermometer_1,
			R.drawable.thermometer_2, R.drawable.thermometer_3, R.drawable.thermometer_4, R.drawable.thermometer_5,
			R.drawable.thermometer_6, R.drawable.thermometer_7, R.drawable.thermometer_8, R.drawable.thermometer_9,
			R.drawable.thermometer_10, R.drawable.thermometer_11, R.drawable.thermometer_12, R.drawable.thermometer_13,
			R.drawable.thermometer_14, R.drawable.thermometer_15, R.drawable.thermometer_16, R.drawable.thermometer_17,
			R.drawable.thermometer_18, R.drawable.thermometer_19, R.drawable.thermometer_20, R.drawable.thermometer_21,
			R.drawable.thermometer_22, R.drawable.thermometer_23, R.drawable.thermometer_24, R.drawable.thermometer_25,
			R.drawable.thermometer_26, R.drawable.thermometer_27, R.drawable.thermometer_28, R.drawable.thermometer_29,
			R.drawable.thermometer_30, R.drawable.thermometer_31, R.drawable.thermometer_32, R.drawable.thermometer_33,
			R.drawable.thermometer_34, R.drawable.thermometer_35, R.drawable.thermometer_36, R.drawable.thermometer_37,
			R.drawable.thermometer_38, R.drawable.thermometer_39, R.drawable.thermometer_40 };

	static final int timeImageArray[] = { R.drawable.t_0, R.drawable.t_1, R.drawable.t_2, R.drawable.t_3,
			R.drawable.t_4, R.drawable.t_5, R.drawable.t_6, R.drawable.t_7, R.drawable.t_8, R.drawable.t_9 };

	static final int highDegreeImageArray[] = { R.drawable.h_0, R.drawable.h_1, R.drawable.h_2, R.drawable.h_3,
			R.drawable.h_4, R.drawable.h_5, R.drawable.h_6, R.drawable.h_7, R.drawable.h_8, R.drawable.h_9 };

	static final int lowDegreeImageArray[] = { R.drawable.l_0, R.drawable.l_1, R.drawable.l_2, R.drawable.l_3,
			R.drawable.l_4, R.drawable.l_5, R.drawable.l_6, R.drawable.l_7, R.drawable.l_8, R.drawable.l_9 };

	static final int refreshIconImageArray[] = { R.drawable.refresh_0, R.drawable.refresh_1, R.drawable.refresh_2,
			R.drawable.refresh_3, R.drawable.refresh_4, R.drawable.refresh_5, R.drawable.refresh_6,
			R.drawable.refresh_7, R.drawable.refresh_8, R.drawable.refresh_9, R.drawable.refresh_10,
			R.drawable.refresh_11 };

	
	/** Called when initialize **/
	public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
		rv = new RemoteViews(context.getPackageName(), R.layout.numeric);
		componentName = new ComponentName(context, Cloud.class);
		widgetMgr = appWidgetManager;
		Service sv;

		Intent toGraphic = new Intent(TO_GRAPHIC_VIEW);
		PendingIntent piToGraphic = PendingIntent.getBroadcast(context, 0, toGraphic, 0);
		rv.setOnClickPendingIntent(R.id.numeric_bar, piToGraphic);

		Intent refreshNumeric = new Intent(REFRESH_NUMERIC);
		PendingIntent piRefreshNumeric = PendingIntent.getBroadcast(context, 0, refreshNumeric, 0);
		rv.setOnClickPendingIntent(R.id.ivRefreshInNumeric, piRefreshNumeric);
		
		updateTimeImageViewResource();
		widgetMgr.updateAppWidget(componentName, rv);
		
		Time time = new Time();
		time.setToNow();
		timer.scheduleAtFixedRate(updateTime, (60 - time.second)*1000, 60000);
		timer.scheduleAtFixedRate(updateWeather, 0, 60000);
	}

	
	@Override
	public void onReceive(Context context, Intent intent) {
		widgetMgr = AppWidgetManager.getInstance(context);

		String action = intent.getAction();
		if (action.equals(TO_GRAPHIC_VIEW)) {
			rv = new RemoteViews(context.getPackageName(), R.layout.graphic);
			
			Intent toNumeric = new Intent(TO_NUMERIC_VIEW);
			PendingIntent piToNumeric = PendingIntent.getBroadcast(context, 0, toNumeric, 0);
			rv.setOnClickPendingIntent(R.id.graphic_bar, piToNumeric);

			Intent refreshGraphic = new Intent(REFRESH_GRAPHIC);
			PendingIntent piRefreshGraphic = PendingIntent.getBroadcast(context, 0, refreshGraphic, 0);
			rv.setOnClickPendingIntent(R.id.ivRefreshInGraphic, piRefreshGraphic);

			isNumericView = false;
			updateTimeImageViewResource();
			updateGraphicTemperature();

			widgetMgr.updateAppWidget(componentName, rv);
		} else if (action.equals(TO_NUMERIC_VIEW)) {
			rv = new RemoteViews(context.getPackageName(), R.layout.numeric);
			
			Intent toGraphic = new Intent(TO_GRAPHIC_VIEW);
			PendingIntent piToGraphic = PendingIntent.getBroadcast(context, 0, toGraphic, 0);
			rv.setOnClickPendingIntent(R.id.numeric_bar, piToGraphic);

			Intent refreshNumeric = new Intent(REFRESH_NUMERIC);
			PendingIntent piRefreshNumeric = PendingIntent.getBroadcast(context, 0, refreshNumeric, 0);
			rv.setOnClickPendingIntent(R.id.ivRefreshInNumeric, piRefreshNumeric);

			isNumericView = true;
			updateTimeImageViewResource();
			setNumericTemperature();
			ViewFlipper vf;
			widgetMgr.updateAppWidget(componentName, rv);
		} else if (action.equals(REFRESH_NUMERIC)) {
			rv = new RemoteViews(context.getPackageName(), R.layout.numeric);
			updateWeatherData();
		} else if (action.equals(REFRESH_GRAPHIC)) {
			rv = new RemoteViews(context.getPackageName(), R.layout.graphic);
			updateWeatherData();
		}

		super.onReceive(context, intent);
	}

	
	@Override
	public void onDeleted(Context context, int[] appWidgetIds) {
		timer.cancel();
	}


	void updateTimeDisplay() {
		updateTimeImageViewResource();
		widgetMgr.updateAppWidget(componentName, rv);
	}


	void updateTimeImageViewResource() {
		Time time = new Time();
		time.setToNow();
		rv.setImageViewResource(isNumericView ? R.id.ivN1stBitHour : R.id.ivG1stBitHour,  timeImageArray[time.hour / 10]);
		rv.setImageViewResource(isNumericView ? R.id.ivN2ndBitHour : R.id.ivG2ndBitHour,  timeImageArray[time.hour % 10]);
		rv.setImageViewResource(isNumericView ? R.id.ivN1stBitMinute : R.id.ivG1stBitMinute,  timeImageArray[time.minute / 10]);
		rv.setImageViewResource(isNumericView ? R.id.ivN2ndBitMinute : R.id.ivG2ndBitMinute,  timeImageArray[time.minute % 10]);
	}
	

	TimerTask updateTime = new TimerTask() {
		public void run() {
			Message message = new Message();
			message.what = TIMER_COMPLETED;
			handler.sendMessage(message);
		}
	};
	

	TimerTask updateWeather = new TimerTask() {
		public void run() {
			Message message = new Message();
			message.what = WEATHER_COMPLETED;
			handler.sendMessage(message);
		}
	};

	
	Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case TIMER_COMPLETED:
				updateTimeDisplay();
				break;
			case WEATHER_COMPLETED:
				updateWeatherData();
				break;
			default:
				super.handleMessage(msg);
			}
		}
	};

	
	void setNumericTemperature() {
		rv.setTextViewText(R.id.tvTemperatureNumeric, actualTemperature + "�");
		rv.setTextViewText(R.id.tvHighTemperature, "H:" + highTemperature + "�");
		rv.setTextViewText(R.id.tvLowTemperature, "L:" + lowTemperature + "�");
		rv.setImageViewResource(R.id.ivArrow, R.drawable.arrows);
	}


	void updateNumericTemperature() {
		setNumericTemperature();
		widgetMgr.updateAppWidget(componentName, rv);
	}


	void updateGraphicTemperature() {
		rv.setTextViewText(R.id.tvTemperatureGraphic, actualTemperature + "�");
		rv.setImageViewResource(R.id.iv1stBitOfHighTemperature, highDegreeImageArray[Integer.parseInt(highTemperature) / 10]);
		rv.setImageViewResource(R.id.iv2ndBitOfHighTemperature, highDegreeImageArray[Integer.parseInt(highTemperature) % 10]);
		rv.setImageViewResource(R.id.iv1stBitOfLowTemperature, lowDegreeImageArray[Integer.parseInt(lowTemperature) / 10]);
		rv.setImageViewResource(R.id.iv2ndBitOfLowTemperature, lowDegreeImageArray[Integer.parseInt(lowTemperature) % 10]);

		int temperature = Integer.parseInt(actualTemperature);
		if (temperature > 40) 
			temperature = 40;
		else if (temperature < 0) 
			temperature = 0;
		rv.setImageViewResource(R.id.ivTemperatureGraphic, thermometerImageArray[temperature]);
	}

	
	void updateWeatherData() {
		Log.i(TAG, "updateWeatherData");
		WeatherSet ws = null;
		startRefreshAni();
	
		try {
			SAXParserFactory spf = SAXParserFactory.newInstance();
			SAXParser sp = spf.newSAXParser();
			XMLReader xr = sp.getXMLReader();
			GoogleWeatherHandler gwh = new GoogleWeatherHandler();
			xr.setContentHandler(gwh);
			URL url = new URL(WEAATHER_URL + "Chengdu");
			InputStreamReader isr = new InputStreamReader(url.openStream(), "GBK");
			InputSource is = new InputSource(isr);
			xr.parse(is);
			ws = gwh.getMyWeatherSet();
			loadWeather = true;
			actualTemperature = ws.getMyCurrentCondition().getTemp_c();
			highTemperature = ws.getMyForecastConditions().get(0).getHigh();
			lowTemperature = ws.getMyForecastConditions().get(0).getLow();
			if (isNumericView)
				updateNumericTemperature();
			else
				updateGraphicTemperature();
		} catch (Exception e) {
			actualTemperature = "21";
			highTemperature = "28";
			lowTemperature = "15";
			if (isNumericView)
				updateNumericTemperature();
			else
				updateGraphicTemperature();
			Log.i(TAG, "Get weathter data error.");
		}
	}


	void startRefreshAni() {
		if (mThread != null) 
			return;
		mThread = new Thread(new Runnable() {
			int imgIdx = 0;
			int loopTimes = 0;
			@Override
			public void run() {
				loadWeather = false;
				while (true) {
					try {
						Thread.sleep(120);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					if ((loadWeather && (imgIdx >= refreshIconImageArray.length - 1)) || (loopTimes >= TURN)) 
						break;
					if (imgIdx >= refreshIconImageArray.length - 1) 
						imgIdx = 0;
					rv.setImageViewResource(isNumericView ? R.id.ivRefreshInNumeric : R.id.ivRefreshInGraphic,  refreshIconImageArray[imgIdx]);
					widgetMgr.updateAppWidget(componentName, rv);
					imgIdx += 2;
					loopTimes++;
				}
				mThread = null;
			}
		});
		mThread.setPriority(Thread.MAX_PRIORITY);
		mThread.start();
	}
}